
#include "ast.h"
#include <assert.h>

const char * ast_node_type_str[] =
{
	"typedef_name",
	"namespace_name",
	"original_namespace_name",
	"namespace_alias",
	"class_name",
	"enum_name",
	"template_name",
	"identifier",
	"literal",
	"integer_literal",
	"character_literal",
	"floating_literal",
	"string_literal",
	"boolean_literal",
	"translation_unit",
	"primary_expression",
	"this_expression", // ***
	"bracket_expression", // ***
	"id_expression",
	"unqualified_id",
	"unqualified_id_dctor", // ***
	"qualified_id",
	"nested_name_specifier",
	"class_or_namespace_name",
	"postfix_expression_rhs_opt",
	"postfix_offset_expression_rhs", // ***
	"postfix_function_expression_rhs", // ***
	"postfix_dereference_expression_rhs", // ***
	"postfix_pointer_expression_rhs", // ***
	"postfix_dec_expression_rhs", // ***
	"postfix_inc_expression_rhs", // ***
	"postfix_expression",
	"postfix_offset_expression", // ***
	"postfix_function_expression", // ***
	"postfix_dereference_expression", // ***
	"postfix_pointer_expression", // ***
	"postfix_dec_expression", // ***
	"postfix_inc_expression", // ***
	"dynamic_cast_expression", // ***
	"static_cast_expression", // ***
	"reinterpret_cast_expression", // ***
	"const_cast_expression", // ***
	"type_id_expression", // ***
	"postfix_ctor_expression", // ***
	"expression_list",
	"pseudo_destructor_name",
	"unary_expression",
	"unary_inc_expression", // ***
	"unary_dec_expression", // ***
	"unary_logical_neg_expression", // ***
	"unary_address_off_expression", // ***
	"unary_dereference_expression", // ***
	"unary_positive_expression", // ***
	"unary_negative_expression", // ***
	"unary_bit_comp_expression", // ***
	"unary_size_of_expression", // ***
	"unary_operator",
	"new_expression",
	"new_placement",
	"new_type_id",
	"new_declarator",
	"direct_new_declarator_rhs_opt",
	"direct_new_declarator",
	"new_initializer",
	"delete_expression",
	"delete_array_expression", // ***
	"cast_expression",
	"pm_expression",
	"multiplicative_expression",
	"multiplicative_mul_expression", // ***
	"multiplicative_div_expression", // ***
	"multiplicative_mod_expression", // ***
	"additive_expression",
	"additive_add_expression", // ***
	"additive_sub_expression", // ***
	"shift_expression",
	"shift_left_expression", // ***
	"shift_right_expression", // ***
	"relational_expression",
	"relational_lt_expression", // ***
	"relational_gt_expression", // ***
	"relational_le_expression", // ***
	"relational_ge_expression", // ***
	"equality_expression",
	"equality_eq_expression", // ***
	"equality_ne_expression", // ***
	"and_expression",
	"exclusive_or_expression",
	"inclusive_or_expression",
	"logical_and_expression",
	"logical_or_expression",
	"conditional_expression",
	"assignment_expression",
	"assignment_mul_expression", // ***
	"assignment_div_expression", // ***
	"assignment_mod_expression", // ***
	"assignment_add_expression", // ***
	"assignment_sub_expression", // ***
	"assignment_sr_expression", // ***
	"assignment_sl_expression", // ***
	"assignment_and_expression", // ***
	"assignment_xor_expression", // ***
	"assignment_or_expression", // ***
	"assignment_operator",
	"expression",
	"constant_expression",
	"statement",
	"labeled_statement",
	"labeled_statement_case", // ***
	"labeled_statement_defualt", // ***
	"expression_statement",
	"compound_statement",
	"statement_seq",
	"selection_statement",
	"selection_statement_if", // ***
	"selection_statement_if_else", // ***
	"selection_statement_switch", // ***
	"condition",
	"iteration_statement",
	"iteration_statement_while", // ***
	"iteration_statement_do_while", // ***
	"iteration_statement_for", // ***
	"for_init_statement",
	"jump_statement",
	"jump_statement_break", // ***
	"jump_statement_continue", // ***
	"jump_statement_return", // ***
	"jump_statement_goto", // ***
	"declaration_statement",
	"declaration_seq",
	"declaration",
	"block_declaration",
	"simple_declaration",
	"decl_specifier",
	"decl_specifier_seq",
	"storage_class_specifier",
	"function_specifier",
	"type_specifier",
	"simple_type_specifier",
	"type_name",
	"elaborated_type_specifier",
	"elaborated_type_specifier_class_key", // ***
	"elaborated_type_specifier_enum", // ***
	"elaborated_type_specifier_typename", // ***
	"enum_specifier",
	"enumerator_list",
	"enumerator_definition",
	"enumerator",
	"namespace_definition",
	"named_namespace_definition",
	"original_namespace_definition",
	"extension_namespace_definition",
	"unnamed_namespace_definition",
	"namespace_body",
	"namespace_alias_definition",
	"qualified_namespace_specifier",
	"using_declaration",
	"using_directive",
	"asm_definition",
	"linkage_specification",
	"init_declarator_list",
	"init_declarator",
	"declarator",
	"ptr_declarator", // ***
	"direct_declarator_rhs_opt",
	"direct_declarator_rhs_func", // ***
	"direct_declarator_rhs_arr", // ***
	"direct_declarator",
	"direct_declarator_func", // ***
	"direct_declarator_arr", // ***
	"ptr_operator",
	"ref_operator", // ***
	"cv_qualifier_seq",
	"cv_qualifier",
	"declarator_id",
	"type_id",
	"type_specifier_seq",
	"abstract_declarator",
	"direct_abstract_declarator_rhs_opt",
	"direct_abstract_declarator_rhs_func", // ***
	"direct_abstract_declarator_rhs_arr", // ***
	"direct_abstract_declarator",
	"direct_abstract_declarator_func", // ***
	"direct_abstract_declarator_arr", // ***
	"parameter_declaration_clause",
	"parameter_declaration_list",
	"parameter_declaration",
	"parameter_declaration_init", // ***
	"function_definition",
	"function_definition_ctor", // ***
	"function_body",
	"initializer",
	"initializer_clause",
	"initializer_list",
	"class_specifier",
	"class_head",
	"class_key",
	"member_specification",
	"member_declaration",
	"member_declarator_list",
	"member_declarator",
	"pure_specifier",
	"constant_initializer",
	"base_clause",
	"base_specifier_list",
	"base_specifier",
	"access_specifier",
	"conversion_function_id",
	"conversion_type_id",
	"conversion_declarator",
	"ctor_initializer",
	"mem_initializer_list",
	"mem_initializer",
	"mem_initializer_id",
	"operator_function_id",
	"operator",
	"template_declaration",
	"template_parameter_list",
	"template_parameter",
	"type_parameter",
	"template_id",
	"template_argument_list",
	"template_argument",
	"explicit_instantiation",
	"explicit_specialization",
	"try_block",
	"function_try_block",
	"handler_seq",
	"handler",
	"exception_declaration",
	"throw_expression",
	"exception_specification",
	"type_id_list",
	"declaration_seq_opt",
	"TEMPLATE_opt",
	"nested_name_specifier_opt",
	"expression_list_opt",
	"COLONCOLON_opt",
	"new_placement_opt",
	"new_initializer_opt",
	"new_declarator_opt",
	"expression_opt",
	"statement_seq_opt",
	"condition_opt",
	"decl_specifier_seq_opt",
	"init_declarator_list_opt",
	"identifier_opt",
	"enumerator_list_opt",
	"TYPENAME_opt",
	"initializer_opt",
	"cv_qualifier_seq_opt",
	"exception_specification_opt",
	"constant_expression_opt",
	"abstract_declarator_opt",
	"type_specifier_seq_opt",
	"direct_abstract_declarator_opt",
	"parameter_declaration_list_opt",
	"ELLIPSIS_opt",
	"ctor_initializer_opt",
	"COMMA_opt",
	"member_specification_opt",
	"base_clause_opt",
	"member_declarator_list_opt",
	"SEMICOLON_opt",
	"pure_specifier_opt",
	"constant_initializer_opt",
	"access_specifier_opt",
	"VIRTUAL_opt",
	"conversion_declarator_opt",
	"EXPORT_opt",
	"handler_seq_opt",
	"assignment_expression_opt",
	"type_id_list_opt",

	"ast_token", // ***
};

const char * ast_node_type_2_str(AstNodeType type)
{
	assert(type < sizeof(ast_node_type_str) / sizeof(ast_node_type_str[0]));

	return ast_node_type_str[type];
}

AstNode::AstNode(AstNodeType type)
	: m_type(type)
{
}

AstNode::~AstNode(void)
{
}

AstNodeType AstNode::getType(void) const
{
	return m_type;
}

void AstNode::pushChild(AstNodePtr child)
{
	m_childs.push_back(child);
}

void AstNode::pushChildList(AstNodePtrList::const_iterator child_iter_begin, AstNodePtrList::const_iterator child_iter_end)
{
	m_childs.insert(m_childs.end(), child_iter_begin, child_iter_end);
}
//
//void AstNode::pushLeftRecursionChild(AstNodePtr child, const AstNodeTypeSet & parent_type_set)
//{
//	assert(parent_type_set.count(m_type));
//
//	if(m_childs.empty() || !parent_type_set.count(m_childs.front()->m_type))
//	{
//		m_childs.insert(m_childs.begin(), child);
//	}
//	else
//	{
//		m_childs.front()->pushLeftRecursionChild(child, parent_type_set);
//	}
//}
//
//void AstNode::pushLeftRecursionChildList(AstNodePtrList::const_iterator child_iter_begin, AstNodePtrList::const_iterator child_iter_end, const AstNodeTypeSet & parent_type_set)
//{
//	assert(parent_type_set.count(m_type));
//
//	if(m_childs.empty() || !parent_type_set.count(m_childs.front()->m_type))
//	{
//		m_childs.insert(m_childs.begin(), child_iter_begin, child_iter_end);
//	}
//	else
//	{
//		m_childs.front()->pushLeftRecursionChildList(child_iter_begin, child_iter_end, parent_type_set);
//	}
//}

std::ostream & AstNode::output(std::ostream & ostr) const
{
	return ostr << ast_node_type_2_str(m_type);
}

AstUninitializedNode::AstUninitializedNode(AstNodeType type, const std::string & file, int line)
	: AstNode(type)
	, m_file(file)
	, m_line(line)
{
}

std::ostream & AstUninitializedNode::output(std::ostream & ostr) const
{
	return AstNode::output(ostr << "<<uninitialized ") << ">>: " << m_file << " (" << m_line << ")";
}

AstTokenNode::AstTokenNode(int tokenID, const std::string & text, int line, int column, AstNodeType type /*= ast_token*/)
	: AstNode(type)
	, m_tokenID(tokenID)
	, m_text(text)
	, m_line(line)
	, m_column(column)
{
}

std::ostream & AstTokenNode::output(std::ostream & ostr) const
{
	return AstNode::output(ostr) << ": " << m_text;
}

AstIdentifierNode::AstIdentifierNode(const std::string & text, AstNodeType type /*= identifier*/)
	: AstNode(type)
	, m_text(text)
{
}

std::ostream & AstIdentifierNode::output(std::ostream & ostr) const
{
	return AstNode::output(ostr) << ": " << m_text;
}

std::ostream & output_indent(std::ostream & ostr, int indent)
{
	for(int i = 0; i < indent; i++)
	{
		ostr << "    ";
	}
	return ostr;
}

void output_ast_tree(std::ostream & ostr, AstNodePtr ast_root, int indent /*= 0*/)
{
	if(ast_root == NULL)
	{
		output_indent(ostr, indent) << "<<UNINITIALIZED>>" << std::endl;
		return;
	}

	assert(ast_root != NULL);

	ast_root->output(output_indent(ostr, indent)) << std::endl;

	AstNodePtrList::const_iterator ast_node_iter = ast_root->m_childs.begin();
	for(; ast_node_iter != ast_root->m_childs.end(); ast_node_iter++)
	{
		output_ast_tree(ostr, *ast_node_iter, indent + 1);
	}
}
